use log::info;

trait Animal {
    fn animal_info(&self) -> &'static str;
}

trait Mammal: Animal {
    fn mammal_info(&self) -> &'static str;
}

trait Canine: Mammal {
    fn canine_info(&self) -> &'static str;
}

struct Dog;

impl Animal for Dog {
    fn animal_info(&self) -> &'static str {
        "I'm an animal"
    }
}

impl Mammal for Dog {
    fn mammal_info(&self) -> &'static str {
        "I'm a mammal"
    }
}

impl Canine for Dog {
    fn canine_info(&self) -> &'static str {
        "I'm a canine"
    }
}

// 判断是否实现特定 trait 的函数
fn check_traits<T>(_obj: &T)
where
    T: Animal + Mammal + Canine,
{
    info!("This object implements Animal, Mammal, and Canine traits");
}

// 专门处理不同层级的函数
fn process_animal<T: Animal>(animal: &T) {
    info!("Processing animal: {}", animal.animal_info());
}

fn process_mammal<T: Mammal>(mammal: &T) {
    info!("Processing mammal: {}", mammal.mammal_info());
    process_animal(mammal); // 可以向上转换
}

fn process_canine<T: Canine>(canine: &T) {
    info!("Processing canine: {}", canine.canine_info());
    process_mammal(canine); // 可以向上转换
}

#[test]
fn main() {
    let dog = Dog;

    check_traits(&dog);
    process_animal(&dog);
    process_mammal(&dog);
    process_canine(&dog);
}